<?php
declare (strict_types = 1);
namespace app\common\model;

use app\common\self\SelfRedis;
use think\Model;

/**
 * @mixin \think\Model
 */
Class BaseModel extends Model
{
    // 数据保存
    public $list = [];
    // 模型 可以再次操作
    public $modelList = [];
    // 拿取数据记录
    public $limit = 10;
    // 分页
    public $page = 1;
    // 过滤只需要的字段值
    public $getField = [];
    // 可转换为数组
    protected $resultSetType = 'collection';
    // 默认缓存库

    // 读取缓存记录默认的配置 模型继承后不得直接替换复制
    private $sr_config = [
        'key' => '' , // 缓存键值 默认会读取 子类的 sr_key
        'order' => 'sort desc', // 默认排序  如果为空 否则 fasle  则 不处理
        'field' => '*', // 拿取的字段  ，默认是 所有
        'where' => [], // 查询的条件 ，默认 没有
        'index' => 5, // 默认缓存库  索引
        'obj_key' => 'id', // 需要转换的键值对
        'obj_sr_key' => '',// 键值对转换的redis  键值
    ];
    // 记录当前模型是否读取缓存数据
    public $sr_status = false;


    /**
     * 分页查询
     * @param $get  get 参数
     * @param $field  拿取的字段名 默认拿取全部字段
     * @param array $where  查询条件  默认空数组
     * @param string $order 排序 默认为sort  可以覆盖
     *  @param array $whereOr or查询构造器 使用效率会低下
     */
    public function queryList($get = [],$field = '*',$where = [],$order = 'sort desc',$whereOr = [])
    {
        if(isset($get['limit']) && $get['limit'] <= 15)
            $this->limit = $get['limit'];
        // 分页参数
        $query = [
            'page' => isset($get['page']) ? $get['page'] : 1
        ];
        // 正常where  查询
        if($whereOr && count($whereOr) > 0){
            $this->modelList = $this->whereOr($whereOr)->where($where)->field($field)->order($order)
                ->paginate($this->limit,false,array('query'=>$query));
        }else{
            $this->modelList = $this->where($where)->field($field)->order($order)
                ->paginate($this->limit,false,array('query'=>$query));
        }
        $this->page = $this->modelList->render();
        $this->list = $this->modelList->toArray();
    }

    /**
     * 读取数据，如果没有则更新缓存,需要结合  函数  setRedisConfig 使用 ，此处不做默认配置 可以调用setSrConfig函数进行默认配置
     * @param bool|true $bool  默认为true表示读取缓存起来的数据,false表示重新去读sql并且存储
     * @return mixed 返回数据
     */
    public function getListCache($bool = true)
    {
        // 如果为true,则拿取缓存
        $sr =  new SelfRedis();
        $sr->redis->select(isset($this->sr_index) ? $this->sr_index : $this->sr_config['index']);
        if($bool){
            $list = $sr->redis->get(isset($this->sr_key) ? $this->sr_key : $this->sr_config['key']);
            // 如果有数据  返回
            if($list){
                $this->sr_status = true;
                return $list;
            }
        }
        // 重新查询sql,并且存储缓存值
        $list = $this->where($this->sr_config['where'])
                ->order($this->sr_config['order'])
                ->field($this->sr_config['field'])
                ->select();
        $sr->redis->set(isset($this->sr_key) ? $this->sr_key : $this->sr_config['key'],$list);
        $this->sr_status = false;
        return $list;
    }

    /**
     * 读取数据，如果没有则更新缓存,需要结合  函数  setRedisConfig 使用 ，此处不做默认配置 可以调用setSrConfig函数进行默认配置
     * @param bool|true $bool  默认为true表示读取缓存起来的数据,false表示重新去读sql并且存储
     * @return mixed 返回数据
     */
    public function getListKeyCache($bool = true,$key = '')
    {
        // 如果为true,则拿取缓存
        $sr =  new SelfRedis();
        $sr->redis->select(isset($this->sr_index) ? $this->sr_index : $this->sr_config['index']);
        if($bool){
            $list = $sr->redis->get(isset($this->obj_sr_key) ? $this->obj_sr_key : $this->sr_config['obj_sr_key']);
            // 如果有数据  返回
            if($list){
                $this->sr_status = true;
//                return $list;
            }
        }

        // 如果没有
        if(!isset($list) || !$list || !is_array($list)){
            // 重新查询sql,并且存储缓存值
            $list = $this->where($this->sr_config['where'])
                ->order($this->sr_config['order'])
                ->field($this->sr_config['field'])
                ->select();
        }

        $newList = [];
        foreach($list as $item){
            if($item['type'] == 1 && $item['val']) $item['val'] = htmlspecialchars_decode($item['val']);
            $newList[
                $key ? $item[$key] : $item[$this->sr_config['obj_key']]
            ] = $item;
        }
        $sr->redis->set(isset($this->obj_sr_key) ? $this->obj_sr_key : $this->sr_config['obj_sr_key'],$newList);
        $this->sr_status = false;
        return $newList;
    }

    /**
     * 设置  redis缓存的配置信息
     * @param array $keys  传递需要更改的键值对
     */
    public function setSrConfig($keys = [])
    {
        foreach($keys as $k => $v){
            if(isset($this->sr_config))
                $this->sr_config[$k] = $v;
        }
    }

    /**
     * 读取redis 缓存配置信息  默认返回数组  全部 传入字符串返回指定键值
     * @param string $key
     */
    public function getSrConfig($key = '')
    {
        return ($key ? (isset($this->sr_config[$key]) ? $this->sr_config[$key] : $this->sr_config) : $this->sr_config);
    }

    /**
     * 过滤只需要的字段值
     */
    public function getFieldData($data = [],$keys = '',$bool = true)
    {
        return getDataKeys($data,$keys ? explode(',',$keys) : $this->getField,$bool);
    }
}